﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Tao.OpenGl;
using Tao.FreeGlut;
using System.Diagnostics;
using TWiStEr.Math;

namespace TWiStEr.OpenGL.Utilities {
	public partial class Camera {
		#region Constructors
		/// <summary>
		/// Main constructor
		/// </summary>
		/// <param name="pos">The position of the camera</param>
		/// <param name="view">The position to where the camera is looking</param>
		/// <param name="up">The Up direction usually (0,1,0)</param>
		/// <param name="fov">The field of view in degrees</param>
		public Camera(Vector pos, Vector view, Vector up, double fov) {
			this.Position = pos;
			this.View = view;
			this.Up = up;
			this.FOV = fov;
		}
		public Camera(double pos_x, double pos_y, double pos_z)
			: this(new Vector(pos_x, pos_y, pos_z), DefaultView, DefaultUp, DefaultFOV) {
			setVerticalSensitivity(0.3f);
		}
		public Camera(double pos_x, double pos_y, double pos_z, double view_x, double view_y, double view_z,
				double up_x, double up_y, double up_z, double fov)
			: this(new Vector(pos_x, pos_y, pos_z), new Vector(view_x, view_y, view_z), new Vector(up_x, up_y, up_z), fov) { }
		public Camera(Vector pos)
			: this(pos, DefaultView, DefaultUp, DefaultFOV) {
			setVerticalSensitivity(0.3f);
		}
		#endregion
		#region Reposition
		public void SetPosition(double pos_x, double pos_y, double pos_z, double view_x, double view_y, double view_z,
			  double up_x, double up_y, double up_z) {
			SetPosition(new Vector(pos_x, pos_y, pos_z), new Vector(view_x, view_y, view_z), new Vector(up_x, up_y, up_z));
		}
		public void SetPosition(Vector pos, Vector view, Vector up) {
			this.Position = pos;
			this.View = IsLockedAtCenterPosition ? AlwaysLookAtCenter.Value : view;
			this.Up = up;
			IsChanged = true;
		}
		#endregion
		#region OpenGL functions
		private void gluOrtho2D() {
			Glu.gluOrtho2D(0.0f, windowWidth, windowHeight, 0.0f);
		}
		private void gluPerspective() {
			Glu.gluPerspective(FOV, aspect, 0.001f, 100*100.0f); // 1 cm to 100 m
		}
		private void gluLookAt() {
			Glu.gluLookAt(Position.X, Position.Y, Position.Z,
				View.X, View.Y, View.Z,
				Up.X, Up.Y, Up.Z);
		}
		public void glSetMatrices() {
			Gl.glMatrixMode(Gl.GL_PROJECTION);
			Gl.glLoadIdentity();
			gluPerspective();
			Gl.glMatrixMode(Gl.GL_MODELVIEW);
			Gl.glLoadIdentity();
			gluLookAt();
			IsChanged = false;
		}
		protected void glutUpdateFullScreen() {
			if (IsFullScreen) {
				Glut.glutFullScreen();
			} else {
				Glut.glutReshapeWindow(windowWidth, windowHeight);
				Glut.glutPositionWindow(0, 20);
			}
		}
		#endregion
	}
}
